package org.ipower.platform.dao.impl;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.ipower.platform.dao.GenericDao;
import org.ipower.platform.domain.Pager;
import org.ipower.platform.domain.QueryCondition;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
/**
 *通用数据访问实现。
 *@param <T>
 * */
public class GenericDaoImpl<T extends Serializable> extends HibernateDaoSupport implements GenericDao<T> {
    private Class<T> entityClass;
    //构造函数。
    @SuppressWarnings("unchecked")
    public GenericDaoImpl(){
        this.entityClass = (Class<T>)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }
    
    @Override
    public void update(T data){
        if(data != null){
            HibernateTemplate hibernateTemp = this.getHibernateTemplate();
            if(hibernateTemp != null){
                //hibernateTemp.saveOrUpdate(data);
                hibernateTemp.merge(data);
            }
        }
    }
    
    @Override
    public void update(List<T> list) {
        if(list != null && list.size() > 0){
            HibernateTemplate hibernateTemp = this.getHibernateTemplate();
            if(hibernateTemp != null){
                for(int i = 0; i < list.size(); i++){
                     this.update(list.get(i));
                      if((i + 1) %  20 == 0){
                          hibernateTemp.flush();
                          hibernateTemp.clear();
                      }
                }
            }
        }
    }
    
    @Override
    public void save(T data){
        if(data != null){
            HibernateTemplate hibernateTemp = this.getHibernateTemplate();
            if(hibernateTemp != null){
                hibernateTemp.save(data);
            }
        }
    }

    @Override
    public void save(List<T> list) {
        if(list != null && list.size() > 0){
            HibernateTemplate hibernateTemp = this.getHibernateTemplate();
            if(hibernateTemp != null){
                for(int i = 0; i <list.size(); i++){
                    this.save(list.get(i));
                    if((i + 1) % 20 ==0){
                        hibernateTemp.flush();
                        hibernateTemp.clear();
                    }
                }
            }
        }
    }

        @Override
    public void delete(Object idValue) {
        if(idValue != null){
            T data = this.load(idValue);
            if(data != null){
                this.delete(data);
            }
        }
    }
    
    @Override
    public void delete(T data) {
        if(data != null){
            HibernateTemplate hibernateTemp = this.getHibernateTemplate();
            if(hibernateTemp != null){
                hibernateTemp.delete(data);
            }
        }
    }
    
    @Override
    public void delete(List<T> list) {
        if(list != null && list.size() > 0){
            HibernateTemplate hibernateTemp = this.getHibernateTemplate();
            if(hibernateTemp != null){
                 for(int i = 0; i < list.size(); i++){
                     this.delete(list.get(i));
                     if((i+1) % 20 == 0){
                         hibernateTemp.flush();
                         hibernateTemp.clear();
                     }
                 }
            }
        }
    }

    @Override
    public void delete(String fieldName, String... values) {
        if(fieldName != null && !fieldName.isEmpty()){
            List<QueryCondition> entities = new ArrayList<QueryCondition>();
            if(values != null && values.length > 0){
                for(int i = 0; i < values.length; i++){
                    entities.add(new QueryCondition(fieldName,values[i], null));
                }
            }else{
                entities.add(new QueryCondition(fieldName,""));
            }
            List<T> list = this.loadAll(entities);
            if(list != null && list.size() > 0){
                this.delete(list);
            }
        }
    }

    @Override
    public T load(Object idValue) {
        T data = null;
        if(idValue != null && (idValue instanceof Serializable)){
            HibernateTemplate hibernateTemp = this.getHibernateTemplate();
            if(hibernateTemp != null && this.entityClass != null){
                data = hibernateTemp.get(this.entityClass, (Serializable)idValue);
            }
        }
        return data;
    }

    @Override
    public List<T> loadAll() {
        HibernateTemplate hibernateTemp = this.getHibernateTemplate();
        if(this.entityClass != null && hibernateTemp != null){
            return hibernateTemp.loadAll(this.entityClass);
        }
        return null;
    }
    
    @Override
    public List<T> loadAll(String fieldName, String... values){
        if(fieldName != null && !fieldName.isEmpty()){
            List<QueryCondition> entities = new ArrayList<QueryCondition>();
            if(values != null && values.length > 0){
                for(int i = 0; i < values.length; i++){
                    entities.add(new QueryCondition(fieldName,values[i]));
                }
            }else{
                entities.add(new QueryCondition(fieldName,""));
            }
            return this.loadAll(entities);
        }
        return null;
    }
    
     @Override
    @SuppressWarnings("unchecked")
    public List<T> loadAll(List<QueryCondition> entities) {
        if(entities != null && entities.size() > 0){
            DetachedCriteria criteria = DetachedCriteria.forClass(this.entityClass);
            HibernateTemplate hibernateTemp = this.getHibernateTemplate();
            if(hibernateTemp != null){
              return  hibernateTemp.findByCriteria(criteria);
            }
        }
        return null;
    }

    @Override
    public Pager<T> findAll(String ascProperty, boolean isAsc, int firstResult, int maxResult) {
       return this.findAll(ascProperty, isAsc, firstResult, maxResult, null);
    }

    @Override
    public Pager<T> findAll(String ascProperty, boolean isAsc, int firstResult, int maxResult, List<QueryCondition> entities) {
        Pager<T> result = new Pager<T>();
        HibernateTemplate hibernateTemp = this.getHibernateTemplate();
        if(this.entityClass != null && hibernateTemp != null){
            DetachedCriteria criteria = DetachedCriteria.forClass(this.entityClass);
            this.AddQueryFilter(criteria, entities);
            if(ascProperty != null && !ascProperty.isEmpty()){
                criteria.addOrder(isAsc ? Order.asc(ascProperty) : Order.desc(ascProperty));
            }
            @SuppressWarnings("unchecked")
            List<T> list = hibernateTemp.findByCriteria(criteria, firstResult, maxResult);
             if(list != null && list.size() > 0){
                 result.setEntityList(list);
                 result.setTotalCounts(hibernateTemp.findByCriteria(criteria).size());
             }
        }
        return result;
    }
    /**
     * 添加查询条件。
     * @param criteria
     * @param entities 查询条件。
     * */
    protected void AddQueryFilter(DetachedCriteria criteria, final List<QueryCondition> entities){
        if(criteria != null && entities != null && entities.size() > 0){
             for(int i = 0; i < entities.size(); i++){
                    QueryCondition qc = entities.get(i);
                    if(qc != null){
                        String property = qc.getExcludeProperty(), value = qc.getValue(), type = qc.getExcludeType();
                        if(property != null && !property.isEmpty()){
                            if(type != null && !type.isEmpty()){
                                if(type.equalsIgnoreCase(QueryCondition.MODE_START)){
                                    criteria.add(Restrictions.like(property, value, MatchMode.START));
                                }else if(type.equalsIgnoreCase(QueryCondition.MODE_END)){
                                    criteria.add(Restrictions.like(property, value, MatchMode.END));
                                }else if(type.equalsIgnoreCase(QueryCondition.MODE_EXACT)){
                                    criteria.add(Restrictions.like(property, value, MatchMode.EXACT));
                                }else{
                                    criteria.add(Restrictions.like(property, value, MatchMode.ANYWHERE));
                                }
                            }else{
                                criteria.add(Restrictions.eq(property, value));
                            }
                        }
                    }
             }
        }
    }
    @Override
    @SuppressWarnings({"unchecked", "unchecked", "unchecked"})
    public List<Object> namedQuery(final String queryName, final String[] paramNames, final Object[] values) {
        List<Object> result = null;
        if(queryName != null && !queryName.isEmpty()){
            HibernateTemplate hibernateTemp = this.getHibernateTemplate();
            if(hibernateTemp != null){
                if(paramNames != null && paramNames.length > 0){
                   result =  hibernateTemp.findByNamedQueryAndNamedParam(queryName, paramNames, values);
                }else if(values != null && values.length > 0){
                    result =hibernateTemp.findByNamedQuery(queryName, values);
                }else{
                    result = hibernateTemp.findByNamedQuery(queryName);
                }
            }
        }
        return result;
    }
}